package com.example.demo.dynamic;


import com.example.demo.data.Goods;
import com.example.demo.data.Orders;
import com.example.demo.executeSql;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.Modifier;
import javassist.CtField;
import javassist.CtNewMethod;

import javassist.bytecode.*;
import javassist.bytecode.annotation.Annotation;
import javassist.bytecode.annotation.ArrayMemberValue;
import javassist.bytecode.annotation.IntegerMemberValue;
import javassist.bytecode.annotation.StringMemberValue;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.lang.reflect.Method;





public class testJavassist {

    @RequestMapping(value="/insertOrder.do")
    @ResponseBody
    public Orders insertOrder(@RequestBody Orders order){
        System.out.println("我是修改的方法!!!");
        executeSql es = new executeSql();
        es.insertOrder(order);
        return order;
    }


    public static void update() throws Exception {
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath("G:\\博士学习\\工作\\数据库\\实现\\new\\target\\classes");
        pool.importPackage("com.example.demo");
        pool.importPackage("com.example.demo.data");
        CtClass cc = pool.get("com.example.demo.myController");

        CtMethod getDetails = cc.getDeclaredMethod("getDetails");
        //getDetails.insertBefore("System.out.println(\"起飞之前准备降落伞\");");
        //getDetails.insertAt(2,"System.out.println(\"成功落地。。。。3\");");


        //getDetails.insertAfter("System.out.println(\"成功落地。。。。4\");");

        try{
            cc.getDeclaredMethod("test");
            System.out.println("test已经存在");
        }catch(Exception e){
            //新增一个方法
            CtMethod ctMethod = new CtMethod(CtClass.voidType, "test", new CtClass[]{}, cc);
            ctMethod.setModifiers(Modifier.PUBLIC);
            ctMethod.setBody("{System.out.println(\"i want to be your friend\");}");
            cc.addMethod(ctMethod);
        }



        //修改一个现有方法
        try{
            CtMethod getGoods = cc.getDeclaredMethod("getGoods");
            getGoods.setBody("{System.out.println(\"代码修改了\");\n"+
                    "executeSql es = new executeSql();\n" +
                    "        $1 = es.selectGoods();\n" +
                    "test();\n" +
                    "        return $1;}");//$1 代表good
            //getGoods.addParameter();
        }catch(Exception e){
            System.out.println(e);
            System.out.println("修改getGoods失败!!!");
        }


        try{
            //删除一个方法
            CtMethod insertOrder = cc.getDeclaredMethod("insertOrder");
            cc.removeMethod(insertOrder);
            //复制并添加一个方法
            String methodStr = "    public Orders insertOrder(Orders order){\n" +
                    "        System.out.println(\"我是修改的方法!!!\");\n" +
                    "        executeSql es = new executeSql();\n" +
                    "        es.insertOrder(order);\n" +
                    "        return order;\n" +
                    "    }";
            CtMethod new_insertOrder = CtNewMethod.make(methodStr, cc);

            //给方法添加注解
            ClassFile ccFile = cc.getClassFile();
            ConstPool constpool = ccFile.getConstPool();
            AnnotationsAttribute attr = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag);
            Annotation annot1 = new Annotation("RequestMapping", constpool);


            StringMemberValue[] elements = {new StringMemberValue("/insertOrder.do",constpool)};
            ArrayMemberValue amv = new ArrayMemberValue(constpool);
            amv.setValue(elements);


            annot1.addMemberValue("value", amv);
            Annotation annot2 = new Annotation("ResponseBody", constpool);
            attr.addAnnotation(annot1);
            attr.addAnnotation(annot2);
            new_insertOrder.getMethodInfo().addAttribute(attr);

            //给参数添加注解.
            ParameterAnnotationsAttribute parameterAtrribute = new ParameterAnnotationsAttribute(
                    constpool, ParameterAnnotationsAttribute.visibleTag);
            Annotation paramAnnot = new Annotation("RequestBody",constpool);
            //paramAnnot.addMemberValue("value", new StringMemberValue("",constPool));
            Annotation[][] paramArrays = new Annotation[1][1];
            paramArrays[0][0] = paramAnnot;
            parameterAtrribute.setAnnotations(paramArrays);
            new_insertOrder.getMethodInfo().addAttribute(parameterAtrribute);

            //添加一个新的参数
            //LocalVariableAttribute localVariableAttribute = new LocalVariableAttribute(constpool);



            //new_insertOrder.setAttribute("int test;",);
            cc.addMethod(new_insertOrder);
        }catch(Exception e){
            System.out.println(e);
        }

        //CtMethod new_insertOrder = CtNewMethod.copy(insertOrder, "", cc, null);



        //为ctClass设置一个父类
        //ctClass.setSuperclass(pool.get("com.javassist.domain.Person"));

        try{
            //为cTclass对象添加一个属性name
            cc.addField(CtField.make("private String name;", cc));
            cc.addMethod(CtMethod.make("public void setName(String name){this.name = name;}", cc));
            cc.addMethod(CtMethod.make("public String getName(){return this.name;}", cc));
        }catch (Exception e){
            System.out.println(e);
        }

        try{//测试修改方法的参数
            ClassFile cf = cc.getClassFile();
            ConstPool cp = cf.getConstPool();
            CtMethod getOrders = cc.getDeclaredMethod("getOrders");
            getOrders.addParameter(CtClass.longType);
            /*
            CodeAttribute ca = minfo.getCodeAttribute();
            String[] paramNames = new String[getOrders.getParameterTypes().length];
            LocalVariableAttribute attr = (LocalVariableAttribute) ca.getAttribute(LocalVariableAttribute.tag);
            System.out.println(minfo);
            System.out.println("-----");
            System.out.println(ca);
            System.out.println("-----");
            System.out.println(attr);
            System.out.println("-----");
            System.out.println(attr.get());*/

            //ca.insertLocalVar(1,1);
            //minfo.setCodeAttribute(ca);


/*
            ClassFile cf = cc.getClassFile();
            ConstPool cp = cf.getConstPool();
            Bytecode code = new Bytecode(cp);
            code.add32bit(10);
            AttributeInfo attrinfo = new AttributeInfo(cp,"test",code.get());
            LocalVariableAttribute new_attr = new LocalVariableAttribute(cp);
            new_attr.set(attrinfo.get());
            ca.set(new_attr.get());
            minfo.setCodeAttribute(ca);*/
/*
            if (attr != null)  {
                int pos = Modifier.isStatic(getOrders.getModifiers()) ? 0 : 1;
                for (int i = 0; i < paramNames.length; i++){
                    paramNames[i] = attr.variableName(i + pos);
                }
            }
            for(int i=0;i< paramNames.length;++i)
                System.out.println(paramNames[i]);*/

        }catch(Exception e){
            System.out.println(e);
        }



        // 导入需要引入的 包
        /*
        cPool.importPackage("com.gdzy.JZFW.service");
        cPool.importPackage("java.text");
        cPool.importPackage("com.gdzy.JZFW.pojo");
        cPool.importPackage("com.gdzy.JZFW.util");
        cPool.importPackage("java.net");
        cPool.importPackage("java.util");
        cPool.importPackage("javax.servlet");
        cPool.importPackage("com.sun.syndication");*/


        //增加一个新方法
        /*
        String methodStr ="public void showParameters(int a,int b){"
                +" System.out.println(\"First parameter: \"+a);"
                +" System.out.println(\"Second parameter: \"+b);"
                +"}";
        CtMethod newMethod = CtNewMethod.make(methodStr, cClass);
        cClass.addMethod(newMethod);*/

        //调用新增的方法
        /*
        cMethod.setBody("{ showParameters($1,$2);return $1*$1*$1+$2*$2*$2; }");
        cClass.writeFile(pathName);*/

        System.out.println("修改完成!!!");
        cc.writeFile("G:\\博士学习\\工作\\数据库\\实现\\new\\target\\classes");


    }

    public static void main(String[] args) {
        try {
            update();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}


